
use sqlx::{Executor,Statement};
use crate::executor::cache::{ExecutorInfo, SaveType};

pub(crate) async fn start_step(
    run_id: u64,
    step_id: u8,
    emids: Vec<u32>,
    is_start: bool,
    tx: &mut sqlx::MySqlConnection,
) -> anyhow::Result<()> {
    if emids.is_empty() {
        return Err(anyhow::anyhow!("用户列表emids不能为空"));
    }
    let tx: &mut sqlx::MySqlConnection = tx;
    if !is_start {
        let init_sql = format!("insert into flow_run_step(run_id,step_id,emid,start_time,state) values");
        let mut sql = emids.iter().fold(init_sql, |sql, emid: &u32| {
            format!("{sql}({run_id},{step_id},{emid},now(),1),")
        });
        sql.pop(); // 去掉最后一个逗号
        sqlx::query(&sql).execute(tx).await?;
    } else {
        let emids: Vec<String> = emids.iter().map(|e| e.to_string()).collect();
        let sql = format!(
            r#"update flow_run_step
        set state=1,start_time=now(),submit_time=null,feed_back=null
        where run_id=? and step_id=? and emid in ({})"#,
            emids.join(",")
        );
        sqlx::query(&sql)
            .bind(run_id)
            .bind(step_id)
            .execute(tx)
            .await?;
    }
    Ok(())
}
pub(crate) async fn insert_step_user_state(
    run_id: u64,
    step_id: u8,
    user: &ExecutorInfo,
    tx: &mut sqlx::Transaction<'_, sqlx::MySql>,
) -> anyhow::Result<()> {
    let tx: &mut sqlx::MySqlConnection = tx;
    let state: u8 = user.task_state.into();
    let sql = r#"insert into flow_run_step(run_id,step_id,emid,state,start_time,submit_time,feed_back)
    values(?,?,?,?,now(),now(),?)"#;
    sqlx::query(&sql)
        .bind(&run_id)
        .bind(&step_id)
        .bind(&user.user_id)
        .bind(&state)
        .bind(&user.feed_back)
        .execute(tx)
        .await?;
    Ok(())
}
pub(crate) async fn update_step_user_state(
    run_id: u64,
    step_id: u8,
    users: &Vec<ExecutorInfo>,
    tx: &mut sqlx::Transaction<'_, sqlx::MySql>,
) -> anyhow::Result<()> {
    let statement = tx.prepare(r#"update flow_run_step
    set state=?,start_time=?,submit_time=?,feed_back=?
    where run_id=? and step_id=? and emid=?"#).await?;
    let tx2: &mut sqlx::MySqlConnection = tx;
    for user in users.iter() {
        if user.save_type != SaveType::Update {
            continue;
        }
        let state: u8 = user.task_state.into();
        let feed_back=user.feed_back.as_ref();
        statement.query()
        .bind(state)
        .bind(user.start_time)
        .bind(user.submit_time)
        .bind(feed_back)
        .bind(run_id)
        .bind(step_id)
        .bind(user.user_id)
        .execute(&mut *tx2)
        .await?;
    }
    Ok(())
}
pub(crate) async fn delete_step_user_state(
    run_id: u64,
    step_id: u8,
    users: &Vec<ExecutorInfo>,
    tx: &mut sqlx::Transaction<'_, sqlx::MySql>,
) -> anyhow::Result<()> {
    let statement = tx.prepare(r#"delete from flow_run_step
    where run_id=? and step_id=? and emid=?"#).await?;
    let uids:Vec<u32>=users.iter().map(|e| e.user_id).collect();
    for uid in uids {
        statement.query()
            .bind(run_id)
            .bind(step_id)
            .bind(uid)
            .execute(&mut **tx)
            .await?;
    }
    Ok(())
}
